package com.hsource.paymentcenter.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.hsource.common.core.domain.message.MessageVO;
import com.hsource.common.utils.DateUtil;
import com.hsource.common.utils.RedisTopicUtil;
import com.hsource.paymentcenter.conf.redis.RedisMessageProducer;
import com.hsource.paymentcenter.conf.wx.WXPay;
import com.hsource.paymentcenter.conf.wx.WXPayConstants;
import com.hsource.paymentcenter.conf.wx.WXPayUtil;
import com.hsource.paymentcenter.conf.wx.WechatConfig;
import com.hsource.paymentcenter.domain.order.Order;
import com.hsource.paymentcenter.domain.pay.Refund;
import com.hsource.paymentcenter.util.IpAdressTool;
import com.hsource.paymentcenter.util.SpringUtils;
import com.hsource.paymentcenter.util.StringUtils;
import com.hsource.paymentcenter.util.redis.RedisKeyUtil;
import com.hsource.paymentcenter.util.redis.RedisUtil;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

/**
 * @author yangYang
 * @version 1.0
 * @date 2020/10/10 16:32
 * @describe 微信支付实现类
 */
@Slf4j
public class WechatPayServiceImpl {
    /**
     * 支付宝退款
     * @param refund
     * @return
     */
    public static boolean refund(Refund refund) throws Exception {

        Map<String, String> resp =null;
        WechatConfig config = SpringUtils.getBean(WechatConfig.class);
        WXPay wxpay = new WXPay(config);
        Map<String,String> paramsMap=new HashMap<>();
        if(StringUtils.isNotBlank(refund.getTransaction_id())) {
            paramsMap.put("transaction_id",refund.getTransaction_id());
        }else{
            paramsMap.put("out_trade_no",refund.getOut_trade_no());
        }
        paramsMap.put("out_refund_no",refund.getOut_refund_no());
        paramsMap.put("total_fee",String.valueOf(new Double(Double.parseDouble(refund.getTotal_fee())*100).intValue()));
        paramsMap.put("refund_fee",String.valueOf(new Double(Double.parseDouble(refund.getRefund_fee())*100).intValue()));
//        paramsMap.put("total_fee","1");
//        paramsMap.put("refund_fee","1");
        try {

            resp = wxpay.refund(paramsMap);

            log.warn("===========AliPayServiceImpl-refund==============="+JSONObject.toJSONString(resp));
            if(resp.get("result_code").equals("SUCCESS")){
                return true;
            }
        }catch (Exception e){
            return false;
        }
        return false;
    }

    /**
     * 支付通知回调
     * @param request 请求体
     * @param payType 支付类型
     */
    public void payNotify(String payType,HttpServletRequest request){
        RedisUtil redisUtil = SpringUtils.getBean(RedisUtil.class);
        RedisMessageProducer redisMessageProducer = SpringUtils.getBean(RedisMessageProducer.class);
        WechatConfig config = SpringUtils.getBean(WechatConfig.class);
        Map<String, String> stringStringMap =new HashMap<>();
        try {
            InputStream inStream = request.getInputStream();
            ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = inStream.read(buffer)) != -1) {
                outSteam.write(buffer, 0, len);
            }
            String resultxml = new String(outSteam.toByteArray(), "utf-8");
            WXPay wxpay=new WXPay(config);
            stringStringMap = wxpay.processResponseXml(resultxml);
            if(stringStringMap.size()>0){
                stringStringMap.put("orderPayType",payType);
            }
            if(!stringStringMap.get("return_code").equals("SUCCESS")){
                stringStringMap.put("return_code","ERROR");
            }
        }catch (Exception e){
            e.printStackTrace();
           log.error("回调信息失败");
        }
        if(stringStringMap.size()>0) {
            String messageId = "" + System.currentTimeMillis();
            MessageVO m = new MessageVO();
            m.setMessageId(messageId);
            m.setTopic(RedisTopicUtil.TOPIC_ORDER_CENTER);
            m.setData(stringStringMap);
            redisMessageProducer.sendMessage(RedisTopicUtil.TOPIC_ORDER_CENTER, m);
        }
    }

    /**
     * 去支付统一下单
     * @param orderId
     * @param request
     */
    public String toOrderPay(String orderId, HttpServletRequest request) throws Exception {
        RedisUtil redisUtil = SpringUtils.getBean(RedisUtil.class);
        WechatConfig config = SpringUtils.getBean(WechatConfig.class);
        Map<String, String> resp =null;

        String orderUnifiedKeyString = RedisKeyUtil.getRedisKeyString(orderId, RedisKeyUtil.ORDER_LIST_UNIFIED);
        if(redisUtil.hasKey(orderUnifiedKeyString)){
            resp = JSONObject.parseObject(JSONObject.toJSONString(redisUtil.get(orderUnifiedKeyString)), Map.class);
            resp.put("timestamp", DateUtil.atime());
            return JSONObject.toJSONString(resp);
        }

        String orderKeyString = RedisKeyUtil.getRedisKeyString(orderId, RedisKeyUtil.ORDER_LIST_STRING);
        if(redisUtil.hasKey(orderKeyString)) {
            WXPay wxpay = new WXPay(config);
            redisUtil.get(orderKeyString).toString();
            Order order = JSONObject.parseObject(redisUtil.get(orderKeyString).toString(), Order.class);
            Map<String,String> paramsMap=new HashMap<>();
            paramsMap.put("body","本草元堂-在线询医");
            paramsMap.put("out_trade_no",order.getId());
            paramsMap.put("total_fee",String.valueOf(order.getPrice()*100));
//            paramsMap.put("total_fee","1");
            paramsMap.put("spbill_create_ip", IpAdressTool.getIpAddr(request));
            paramsMap.put("notify_url",config.getNotifyUrl());
            paramsMap.put("trade_type","APP");
            try {
                resp = wxpay.unifiedOrder(paramsMap);
                if(resp.get("result_code").equals("SUCCESS")){
                    //二次签名
                    Map<String,String> appSign=new HashMap<>();
                    appSign.put("appid",config.getAppID());
                    appSign.put("partnerid",config.getMchID());
                    appSign.put("prepayid",resp.get("prepay_id"));
                    appSign.put("noncestr",WXPayUtil.generateNonceStr());
                    appSign.put("timestamp", DateUtil.atime());
                    appSign.put("package","Sign=WXPay");
                    resp.put("sign",WXPayUtil.generateSignature(appSign, config.getKey(),WXPayConstants.SignType.HMACSHA256).substring(0,30));
                    resp.put("timestamp", DateUtil.atime());
                    redisUtil.expire(orderKeyString,3600);

                    //缓存统一下单结果一小时
                    String respString = JSONObject.toJSONString(resp);
                    redisUtil.set(orderUnifiedKeyString,resp);
                    redisUtil.expire(orderUnifiedKeyString,3600);

                    return respString;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}
